home *** CD-ROM | disk | FTP | other *** search
- /*
- rpc.c
-
- Copyright (c) 2000 Dug Song <dugsong@monkey.org>
-
- $Id: rpc.c,v 1.3 2000/05/17 16:05:09 dugsong Exp $
- */
-
- #include <sys/types.h>
- #include <rpc/rpc.h>
- #include <stdio.h>
- #include <string.h>
- #include "decode.h"
- #include "rpc.h"
-
- #define FRAGLEN(x) (x & 0x7fffffff)
- #define LASTFRAG(x) (x & (1 << 31))
-
- #define XIDMAPSIZE 64
-
- static struct xid_map xid_maps[XIDMAPSIZE];
-
- static int xid_map_next = 0;
- static int xid_map_hint = 0;
-
- /* xid_map adapted from tcpdump's print-nfs.c */
-
- void
- xid_map_enter(u_long xid, u_long prog, void *data)
- {
- struct xid_map *mp;
-
- mp = &xid_maps[xid_map_next];
-
- if (++xid_map_next >= XIDMAPSIZE)
- xid_map_next = 0;
-
- mp->xid = xid;
- mp->prog = prog;
- mp->data = data;
- }
-
- struct xid_map *
- xid_map_find(int xid)
- {
- struct xid_map *mp;
- int i;
-
- /* Start searching from where we last left off. */
- i = xid_map_hint;
- do {
- mp = &xid_maps[i];
- if (mp->xid == xid) {
- /* match */
- xid_map_hint = i;
- return (mp);
- }
- if (++i >= XIDMAPSIZE)
- i = 0;
- } while (i != xid_map_hint);
-
- return (NULL);
- }
-
- int
- rpc_decode(u_char *buf, int len, struct rpc_msg *msg)
- {
- XDR xdrs;
- u_long *p, fraghdr;
- u_char *tmp;
- int stat, tmplen;
-
- if (len < 20)
- return (0);
-
- p = (u_long *)&buf[4];
-
- /* If not recognizably RPC, try TCP record defragmentation */
- if (ntohl(*p) != CALL && ntohl(*p) != REPLY) {
- tmp = buf;
- tmplen = 0;
-
- for (;;) {
- fraghdr = ntohl(*(u_long *)tmp);
-
- if (FRAGLEN(fraghdr) + 4 > len)
- return (0);
-
- len -= 4;
- memmove(tmp, tmp + 4, len);
- tmplen += FRAGLEN(fraghdr);
-
- if (LASTFRAG(fraghdr))
- break;
-
- tmp += FRAGLEN(fraghdr);
- len -= FRAGLEN(fraghdr);
-
- if (len < 4)
- return (0);
- }
- len = tmplen;
- }
- /* Decode RPC message. */
- if (ntohl(((struct rpc_msg *)buf)->rm_direction) == CALL) {
- xdrmem_create(&xdrs, buf, len, XDR_DECODE);
-
- if (!xdr_callmsg(&xdrs, msg)) {
- xdr_destroy(&xdrs);
- return (0);
- }
- }
- else if (ntohl(((struct rpc_msg *)buf)->rm_direction) == REPLY) {
- msg->acpted_rply.ar_results.proc = (xdrproc_t) xdr_void;
- xdrmem_create(&xdrs, buf, len, XDR_DECODE);
-
- if (!xdr_replymsg(&xdrs, msg)) {
- xdr_destroy(&xdrs);
- return (0);
- }
- }
- stat = xdr_getpos(&xdrs);
- xdr_destroy(&xdrs);
-
- return (stat);
- }
-
-